package embyparse.tokenizer;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import embyparse.noobparser.Constants;
import embyparse.util.TokenStream;

public class Tokenizer implements TokenStream{

	Scanner s;
	BufferedReader input;
	int currentline =-1;
	ArrayList<Token> tokens;

	public Tokenizer(File file){
		try {
			input = new BufferedReader(new FileReader(file));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		s = new Scanner(input);
		currentline = 1;
		tokens = new ArrayList<Token>();
	}

	public Tokenizer(InputStream in){
		s = new Scanner(in);
	}


	public Token next() {
		if( tokens.size()>0){
			return tokens.remove(0);
		}
		else{
		populateTokens();
		return next();
		}
	}
	
	public void close(){
		try {
			input.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void populateTokens(){
		//TOKENIZING PROCESS:
				//Take a line form scanner
		String line = s.nextLine();
		tokenizeLine(line);
		currentline++;
	}

	public void tokenizeLine(String line){
		StringDummifier d = new StringDummifier();
		//System.out.println(line);
		line = d.dummify(line);
		//System.out.println(line);
		line = presplit(line);
		//System.out.println(line);

		String[] splitted = line.split(" ");
		for(int i = 0; i<splitted.length; i++){
			if(splitted[i].length()>0)
			tokens.add( new Token( d.dedummify(splitted[i]),currentline )  );
		}
	}

	public boolean hasNext(){
		return (tokens.size()!=0) || s.hasNext();
	}

	public static String presplit(String s){
		//PRE_SPLIT
		//Replace strings with dummy strings
		//Remove comments, if any
		//Substitute Multicharacter Operators
		//Space out operators/parentheses/semicolons
		//Resubstitute Multicharacter Operators
		//Split string based on whitespace. You will now have an array of strings

		s = s.replaceAll("//.*", ""); //remove comments
		s = s.replaceAll("[\\s&&[^\\n]]"," "); //turn random whitespace into spaces.
		//s = s.replaceAll(";+", ";");// get rid of redundant semicolons.
		//s = s.replaceAll(",", " "); //space out commas
		//s = s.replaceAll(";[\\s+]", ";");// remove whitespace after semicolons

		s = MultiCharacterOperators.convert(s);

		//space out operators
		for( int i = 0; i<Constants.SINGLE_CHAR_SYNTAX.length; i++){
			CharSequence c = Constants.SINGLE_CHAR_SYNTAX[i];
			s = s.replace( c , " "+Constants.SINGLE_CHAR_SYNTAX[i]+" "); //space out operators
		}
		s = MultiCharacterOperators.revert(s);

		//doubles tokenizing
		//space periods followed by a character
		ArrayList<String> replacements = patternFind(s,"\\.[^0-9]");
		for(int i = 0; i<replacements.size(); i++){
			String cheese = replacements.get(i);
			s = s.replace(cheese, " . "+cheese.substring(1));
		}

		//negatives tokenizing
		/*
		replacements = patternFind(s,"[^0-9a-z]-[0-9]");
		for(int i = 0; i<replacements.size(); i++){
			String cheese = replacements.get(i);
			s = s.replace(cheese, "negatve_literal");
		}
		*/


		return s;
	}

	private static ArrayList<String> patternFind(String source , String regex){
		Pattern p = Pattern.compile(regex);
		Matcher matcher = p.matcher(source);
		ArrayList<String> replacements = new ArrayList<String>();
		while(matcher.find()){
			int first = matcher.start();
			int end = matcher.end();
			String s2 = source.substring(first, end);
			replacements.add(s2);
		}
		return replacements;
	}

}
